package modules.pathloss.model;

import datatypes.Antenna;
import tools.settings.Settings;
import tools.settings.SettingsMissingException;

/**
 *
 * @author Lynne Vandousselaere
 */
public class CostHata implements PathLossModel {

    //TODO add costhata plm verifysettings here
    private String[] snames = {"coverage_requirement", "urban_correction",
        "indoor", "ms_height"};

    @Override
    public double[] getLogDistance(Settings settings, Antenna a)
            throws SettingsMissingException {
        if (!settings.contains(snames))
            throw SettingsMissingException.generate("PLM", "CostHata", snames);

        double f = a.getFrequency();
        float p = Float.parseFloat(settings.getSettingsValue("coverage_requirement")) / 100;
        double hb = a.getHeight();
        if(hb == 0)
            hb = 1;
        double hm = Double.parseDouble(settings.getSettingsValue("ms_height"));

        double[] mapl = new double[2];

        mapl[0] = 46.3 + (33.9 * Math.log10(f)) - (13.82 * Math.log10(hb))
                - getAntennaHeightCorrectionTerm(f, hm)
                + Calculator.getUrbanCorrection(a, settings)
                + Calculator.getShadowingMargin(a, settings, p);
        mapl[1] = 44.9 - (6.55 * Math.log10(hb));

        return mapl;
    }

    public double getPathLoss(Settings settings, Antenna a, double distance)
            throws SettingsMissingException {
        if (!settings.contains(snames))
            throw SettingsMissingException.generate("PLM", "CostHata", snames);

        double f = a.getFrequency();
        float p = Float.parseFloat(settings.getSettingsValue("coverage_requirement")) /100;
        double hm = Double.parseDouble(settings.getSettingsValue("ms_height"));
        double hb = a.getHeight();
        if(hb == 0)
            hb = 1;
        double d = distance / 1000; // to km.
        double ah = getAntennaHeightCorrectionTerm(f, hm);
        double Cm = Calculator.getUrbanCorrection(a, settings);
        double s = Calculator.getShadowingMargin(a, settings, p);

        return 46.3 + (33.9 * Math.log10(f)) - (13.82 * Math.log10(hb)) - ah +
                (44.9 - (6.55 * Math.log10(hb))) * Math.log10(d) + Cm + s;
    }

    public String[] getRequiredSettingNames() {
        return snames;
    }

    private double getAntennaHeightCorrectionTerm(double f, double hm) {
        return (1.1 * Math.log10(f) - 0.7) * hm - (1.56 * Math.log10(f) - 0.8);
    }
}
